﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Practices.Unity;
using Infrastucture;
using TimeSplicerModule.Factories;
using TimeSplicerModule.DomainModels;
using TimeSplicerModule.Security;
using TimeSplicerModule.ViewModels;

namespace TimeSplicerModule.Services
{
    public interface IApplicationRoleService
    {
        ApplicationRoleViewModel CreateNew();
        ApplicationRoleViewModel Get(Guid applicationRoleGuid);
        ApplicationRoleViewModel Save(ApplicationRoleViewModel model);
    }

    public class ApplicationRoleService : IApplicationRoleService
    {
        private readonly IUnityContainer _container;
        private ISession _session;
        private readonly IApplicationRoleFactory _applicationRoleFactory;
        private readonly IApplicationItemFactory _applicationItemFactory;
        private readonly IApplicationPermissionFactory _applicationPermissionFactory;
        private readonly IApplicationRolePermissionFactory _applicationRolePermissionFactory;

        public ApplicationRoleService(IUnityContainer container, IApplicationRoleFactory applicationRoleFactory, IApplicationItemFactory applicationItemFactory,
            IApplicationPermissionFactory applicationPermissionFactory, IApplicationRolePermissionFactory applicationRolePermissionFactory)
        {
            _container = container;
            _applicationRoleFactory = applicationRoleFactory;
            _applicationItemFactory = applicationItemFactory;
            _applicationPermissionFactory = applicationPermissionFactory;
            _applicationRolePermissionFactory = applicationRolePermissionFactory;
        }

        public ApplicationRoleViewModel CreateNew()
        {
            _session = _container.Resolve<ISession>();

            var role = _applicationRoleFactory.CreateNew();
            role.Permissions = new List<ApplicationRolePermissionModel>();
            var roles = _applicationRoleFactory.GetList();
            var items = _applicationItemFactory.GetList();
            var permissions = _applicationPermissionFactory.GetList();
            var notAllowed = permissions.FirstOrDefault(x => x.Permission == ApplicationPermission.Not_Allowed);

            // need to add the items to the permission list with a default of not allowed
            foreach (var i in items)
            {
                var p = _applicationRolePermissionFactory.CreateNew(role.ApplicationRoleGuid, i.ApplicationItemGuid, notAllowed.ApplicationPermissionGuid,
                    role, i, notAllowed);
                p.ApplicationPermissions = permissions;

                role.Permissions.Add(p);
            }

            // convert and return
            var model = ModelConverter.ToModel<ApplicationRoleViewModel>(role);
            model.ApplicationItems = items;
            model.ApplicationPermissions = permissions;

            return model;
        }

        public ApplicationRoleViewModel Get(Guid applicationRoleGuid)
        {
            _session = _container.Resolve<ISession>();

            var role = _applicationRoleFactory.Get(x => x.ApplicationRoleGuid == applicationRoleGuid);
            var roles = _applicationRoleFactory.GetList();
            var items = _applicationItemFactory.GetList();
            var permissions = _applicationPermissionFactory.GetList();
            role.Permissions = _applicationRolePermissionFactory.GetList(x => x.ApplicationRoleGuid == role.ApplicationRoleGuid,
                roles, items, permissions);

            var notAllowed = permissions.FirstOrDefault(x => x.Permission == ApplicationPermission.Not_Allowed);

            // need to check to see if all are attached to this user and if not add them
            foreach (var i in items)
            {
                var existing = role.Permissions.FirstOrDefault(x => x.ApplicationItemGuid == i.ApplicationItemGuid);

                if (existing == null)
                {
                    var p = _applicationRolePermissionFactory.CreateNew(role.ApplicationRoleGuid, i.ApplicationItemGuid, notAllowed.ApplicationPermissionGuid,
                        role, i, notAllowed);
                    p.ApplicationPermissions = permissions;

                    role.Permissions.Add(p);
                }
                else
                {
                    existing.ApplicationPermissions = permissions;
                }
            }

            // convert and return
            var model = ModelConverter.ToModel<ApplicationRoleViewModel>(role);
            model.ApplicationItems = items;
            model.ApplicationPermissions = permissions;

            return model;
        }

        public ApplicationRoleViewModel Save(ApplicationRoleViewModel model)
        {
            _session = _container.Resolve<ISession>();

            var role = ModelConverter.ToModel<ApplicationRoleModel>(model);
            role = _applicationRoleFactory.Upsert(role);

            role.Permissions.ForEach(x =>
                {
                    x = _applicationRolePermissionFactory.Upsert(x);
                });


            return Get(role.ApplicationRoleGuid);
        }
    }
}
